from typing import Optional, Any, Dict
from pydantic_settings import BaseSettings
from functools import lru_cache
from pathlib import Path
import logging

logger = logging.getLogger(__name__)

class Settings(BaseSettings):
    """应用配置类"""
    
    # 模型配置
    MODEL_NAME: str = "TinyLlama"
    MODEL_CACHE_DIR: str = "/Users/xyl/Downloads/TinyLlama"
    DEVICE: str = "mps"
    USE_MPS: bool = True
    MPS_FALLBACK: bool = True
    MAX_GPU_MEMORY: str = "4GiB"
    
    # 推理参数
    MAX_NEW_TOKENS: int = 256
    TEMPERATURE: float = 0.7
    TOP_K: int = 50
    TOP_P: float = 0.95
    
    # 服务配置
    HOST: str = "0.0.0.0"
    PORT: int = 8000
    LOG_LEVEL: str = "INFO"
    
    # 会话配置
    MAX_HISTORY_LENGTH: int = 10
    CONVERSATION_TIMEOUT: int = 3600
    
    # 数据库配置
    DB_TYPE: str = "sqlite"
    DB_HOST: str = "localhost"
    DB_PORT: int = 5432
    DB_NAME: str = "tinyllama_chat"
    DB_USER: str = ""
    DB_PASSWORD: str = ""
    DB_URL: str = "sqlite:///./data/chat_history.db"
    
    # 安全配置
    API_KEY_REQUIRED: bool = False
    API_KEY: str = ""
    
    # 资源限制
    MAX_CONCURRENT_REQUESTS: int = 5
    REQUEST_TIMEOUT: int = 30
    
    # 缓存配置
    ENABLE_CACHE: bool = True
    CACHE_TYPE: str = "memory"
    REDIS_URL: str = ""
    
    # 开发模式
    DEBUG: bool = False
    ENVIRONMENT: str = "development"
    
    # 下载配置
    FORCE_DOWNLOAD: bool = False
    HTTP_PROXY: str = ""
    HF_TOKEN: str = ""
    
    @property
    def model_path(self) -> Path:
        """获取模型绝对路径"""
        try:
            path = Path(self.MODEL_CACHE_DIR)
            if not path.is_absolute():
                path = Path.cwd() / self.MODEL_CACHE_DIR
            
            resolved_path = path.resolve()
            logger.info(f"解析后的模型路径: {resolved_path}")
            
            return resolved_path
            
        except Exception as e:
            logger.error(f"模型路径解析错误: {e}")
            raise
    
    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"
        case_sensitive = True
        extra = "ignore"  # 允许额外的配置项

@lru_cache()
def get_settings() -> Settings:
    """获取配置单例"""
    try:
        settings = Settings()
        logger.info(f"成功加载配置，MODEL_CACHE_DIR = {settings.MODEL_CACHE_DIR}")
        return settings
    except Exception as e:
        logger.error(f"加载配置失败: {e}")
        raise

# 导出配置实例
settings = get_settings()